//
//  WBStatusViewModel.swift
//  DXWeibo
//
//  Created by dx on 2017/1/15.
//  Copyright © 2017年 dx. All rights reserved.
//

import Foundation

/// 单条微博的视图模型
/**
 如果没有任何父类，但是希望在开发时调试，输出调试信息，需要
 1. 遵守 CustomStringConvertible
 2. 实现 description 计算型属性
 
 关于表格的性能优化
 
 - 尽量少计算，所有需要的素材提前计算好
 - 控件上不要设置圆角半径，注意图像渲染属性
 - 不要动态创建控件，所有的提前创建好，根据数据隐藏／显示
 - cell 中控件的数量和层次越少越好
 - 要测量，不要猜测！
 
 */
class WBStatusViewModel: CustomStringConvertible {
    
    /// 微博模型
    var status: WBStatus
    
    /// 会员图标 - 存储型属性（用内存换CPU）
    var memberIcon: UIImage?
    /// 认证图标
    var vipIcon: UIImage?
    
    /// 转发文字(工具栏)
    var retweetedStr: String?
    /// 评论文字
    var commentStr: String?
    /// 点赞文字
    var likeStr:String?
    
    /// 配图视图大小
    var pictureViewSize = CGSize()
    
    /// 如果是被转发的微博，原创微博一定没有图
    var picURLs: [WBStatusPicture]? {
        return status.retweeted_status?.pic_urls ?? status.pic_urls
    }
    
    /// 微博正文的属性文本
    var statusAttrText: NSAttributedString?
    /// 转发文字的属性文本∫
    var retweetedAttrText: NSAttributedString?
    
    /// 行高
    var rowHeight: CGFloat = 0
    
    /// 构造函数
    ///
    /// - Parameter model: 微博模型
    init(model: WBStatus) {
        
        status = model
        
        // ***提前计算出会员图标，以后不用再计算!!!/会员等级 0-6
        let imageName = "common_icon_membership_level\(model.user?.mbrank ?? 1)"
        memberIcon = UIImage(named: imageName)
        
        // 认证类型，-1:没有认证，0:用户认证，2，3，5:企业认证，220:达人
        switch status.user?.verified_type ?? -1 {
        case 0:
            vipIcon = UIImage(named: "avatar_vip")
        case 2,3,5:
            vipIcon = UIImage(named: "avatar_enterprise_vip")
        case 220:
            vipIcon = UIImage(named: "avatar_grassroot")
        default:
            break
        }
        
        // 设置底部计数字符串
        // 测试
        // model.reposts_count = Int(arc4random_uniform(100000))
        retweetedStr = countString(count: model.reposts_count, defaultStr: "转发")
        commentStr = countString(count: model.comments_count, defaultStr: "评论")
        likeStr = countString(count: model.attitudes_count, defaultStr: "赞")

        // 计算配图视图大小
        pictureViewSize = calcPictureViewSize(count: picURLs?.count)
        
        // --- 设置微博文本 ---
        let originFont = UIFont.systemFont(ofSize: 17)
        let retweetedFont = UIFont.systemFont(ofSize: 16)
        
        // 设置微博正文的属性文本
        statusAttrText = CZEmoticonManager.shared.emoticonString(string: model.text ?? "", font: originFont)
        
        // 设置被转发微博的属性文本
        let rText = "@" + (status.retweeted_status?.user?.screen_name ?? "") + ":" + (status.retweeted_status?.text ?? "")
        retweetedAttrText = CZEmoticonManager.shared.emoticonString(string: rText, font: retweetedFont)
        
        // 计算行高
        updateRowHeight()
    }
    
    var description: String {
        return status.description
    }
    
    /// 根据当前的视图模型计算行高
    func updateRowHeight() {
        
        let margin: CGFloat = 12
        let iconHeight: CGFloat = 34
        let toolbarHeight: CGFloat = 35
        
        var height: CGFloat = 0
        
        let viewSize = CGSize(width: UIScreen.cz_screenWidth() - 2 * margin, height: CGFloat(MAXFLOAT))
        
        // 1. 计算顶部位置
        height = 2 * margin + iconHeight + margin
        
        // 2. 正文属性文本的高度
        if let text = statusAttrText {
            
            /**
             1> 预期尺寸，宽度固定，高度尽量大
             2> 选项，换行文本，统一使用 useLineFragmentOrigin
             3> attributes，指定字体字典(替换成属性文本之后不需要)
             */
            height += text.boundingRect(with: viewSize, options: [.usesLineFragmentOrigin], context: nil).height
        }
        
        // 3. 判断是否转发微博
        if status.retweeted_status != nil {
            
            height += 2 * margin
            
            // 转发文本的高度 - 一定要用 retweetedText，拼接了@用户名：微博文字
            if let text = retweetedAttrText {
                
                height += text.boundingRect(with: viewSize, options: [.usesLineFragmentOrigin], context: nil).height
            }
        }
        
        // 4. 配图视图
        height += pictureViewSize.height + margin
        
        // 5. 底部工具栏
        height += toolbarHeight
        
        // 6. 使用属性记录
        rowHeight = height
    }
    
    /// 使用单个图像，更新配图视图的大小
    ///
    /// - Parameter image: 网络缓存的单张图像
    func updateSingleImageSize(image: UIImage) {
        
        var size = image.size
        
        let maxWidth: CGFloat = 200
        let minWidth: CGFloat = 40
        
        // 过宽图像处理
        if size.width > maxWidth {
            // 设置最大宽度
            size.width = maxWidth
            // 等比例调整高度
            size.height = size.width * image.size.height / image.size.width
        }
        
        // 过窄图像处理
        if size.width < minWidth {
            size.width = minWidth
            // 特殊处理高度
            size.height = size.width * image.size.height / image.size.width / 4
        }
        
        // 过高图像处理 - 图片填充模式就是 scaleToFill，高度减小，会自动裁切
        if size.height > maxWidth {
            size.height = maxWidth
        }
        
        // *** 在工作中，如果看到代码中有些疑惑的分支处理，千万不要动！
        
        size.height += WBStatusPictureViewOutterMargin
        
        // 重新设置配图视图的大小
        pictureViewSize = size
        
        // 更新行高
        updateRowHeight()
    }
    
    /// 计算配图视图大小
    private func calcPictureViewSize(count: Int?) -> CGSize {
        
        if count == 0 || count == nil {
            return CGSize()
        }
        
        // 计算行数
        let row = CGFloat((count! - 1) / 3 + 1)
        
        // 高度
        let WBStatusPictureViewHeight = WBStatusPictureViewOutterMargin + row * WBStatusPictureItemWidth + (row - 1) * WBStatusPictureViewInnerMargin
        
        return CGSize(width: WBStatusPictureViewWidth, height: WBStatusPictureViewHeight)
    }
    
    private func countString(count: Int, defaultStr: String) -> String {
        
        if count == 0 {
            return defaultStr
        } else if count < 10000 {
            return "\(count)"
        } else {
            return String(format: "%.02f 万", Double(count) / 10000)
        }
    }
}















